package com.thrsdk.common.network.request;

import android.app.Fragment;
import android.content.Context;
import android.text.TextUtils;

import com.dy.google.gson.GsonBuilder;
import com.thrsdk.common.base.BaseParams;
import com.thrsdk.common.network.BaseRetrofitClient;
import com.thrsdk.common.network.GetRequest;
import com.thrsdk.common.network.PostRequest;
import com.thrsdk.common.network.result.BaseBean;
import com.thrsdk.log.LogUtils;
import com.thrsdk.model.data.DeviceInfo;
import com.thrsdk.mylibrary.BuildConfig;
import com.thrsdk.network.ApiException;
import com.thrsdk.network.HttpStatusCode;
import com.thrsdk.utils.DomainHelper;
import com.thrsdk.utils.GsonUtils;
import com.thrsdk.utils.LifeCycleUtils;
import com.thrsdk.utils.NetworkUtils;
import com.thrsdk.utils.ThreadUtils;
import com.thrsdk.utils.ToastUtils;

import java.lang.reflect.Type;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import af.okhttp3.ResponseBody;
import dy.retrofit2.Call;
import dy.retrofit2.Callback;
import dy.retrofit2.Response;
import dy.retrofit2.Retrofit;

/**
 * Retrofit请求类 （get和post）
 */
public class HttpRequestClient {
    private static final String TAG = "HttpRequestClient";
    private static Retrofit retrofit;

    /**
     * 发送GET网络请求
     *
     * @param url           请求地址
     * @param clazz         返回的数据类型
     * @param resultHandler 回调
     * @param <T>           泛型
     */
    public static <T> void sendGetRequest(String url, final Class<T> clazz, final ResultHandler<T> resultHandler) {
        // 判断网络连接状况
        if (resultHandler.isNetDisconnected()) {
            resultHandler.onFailure(new ApiException("", HttpStatusCode.NO_NET_WORK));
            return;
        }
        GetRequest getRequest = retrofit.create(GetRequest.class);
        // 构建请求
        Call<ResponseBody> call = getRequest.getUrl(url);
        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                try {
                    ResponseBody body = response.body();
                    if (body == null) {
//                        resultHandler.onServerError();
                        resultHandler.onFailure(new ApiException("", HttpStatusCode.RESPONSE_BODY_NULL));
                        return;
                    }
                    String string = body.string();
                    T t = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().fromJson(string, clazz);
                    resultHandler.onSuccess(t, true, "success");
                } catch (Exception e) {
                    e.printStackTrace();
                    resultHandler.onFailure(e);
                }
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                resultHandler.onFailure(t);
            }
        });
    }

    /**
     * 发送post网络请求
     *
     * @param url           请求地址
     * @param params        参数对象
     * @param dataType      返回的数据类型
     * @param resultHandler 回调
     * @param <T>           泛型
     */
    public static <T> void sendPostRequest(String url, Object params, final Type dataType, final ResultHandler<T> resultHandler) {
        String baseDomain = BuildConfig.baseHttp;
        if (url.contains(baseDomain)) {
            String[] urlarray = url.split(baseDomain);
            if (urlarray.length > 1) {
                String address = urlarray[1];
                url = DomainHelper.getInstance().getDomainMain() + address;
            }
        }

        // 判断网络连接状况
        if (resultHandler.isNetDisconnected()) {
            resultHandler.onFailure(new ApiException("", HttpStatusCode.NO_NET_WORK));
            return;
        }
        if (null == retrofit) {
            retrofit = BaseRetrofitClient.getInstance(resultHandler.context).getDefaultRetrofit();
        }
        PostRequest postRequest = retrofit.create(PostRequest.class);
        DeviceInfo deviceInfo = new DeviceInfo(resultHandler.context);
        // 参数
        BaseParams baseParams = new BaseParams<>(deviceInfo, params);
        // 构建请求
        Call<ResponseBody> call = postRequest.postMap(url, baseParams.getParams());
//        Call<ResponseBody> call = postRequest.postMap(url, GsonUtils.getInstance().hashMapToJson(baseParams.getParams()));
        String finalUrl = url;
        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                if (!resultHandler.checkLifeCycle()) {
                    // context，activity或者fragment已销毁，不回调直接返回
                    return;
                }
                try {
                    ResponseBody body = response.body();
                    if (body == null) {
//                        resultHandler.onServerError();
                        // TODO: 2023-03-21 网络域名错误
                        int code = response.code();
                        if (code == 501 || code == 502 || code == 503 || code == 504 || code == 505) {
                            changeHost(finalUrl, params, dataType, resultHandler, new ApiException("", HttpStatusCode.RESPONSE_BODY_NULL));
                        } else {
                            resultHandler.onFailure(new ApiException("网络请求失败", HttpStatusCode.RESPONSE_BODY_NULL));
                        }
                        return;
                    }
                    String string = body.string();
                    BaseBean baseBean = GsonUtils.getInstance().fromJson(string, BaseBean.class);
                    //基于ParameterizedType实现泛型类类型参数化
//                    String str = baseBean.getData().toString();
                    T t = null;
                    if (baseBean.isResult()) {
                        t = GsonUtils.getInstance().fromJson(string, dataType);
                    }
                    resultHandler.onSuccess(t, baseBean.isResult(), baseBean.getMsg());
                } catch (Exception e) {
                    e.printStackTrace();
                    LogUtils.getInstance().e(e, "解析异常!!!");
                    resultHandler.onFailure(e);
                }
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                if (!resultHandler.checkLifeCycle()) {
                    // context，activity或者fragment已销毁，不回调直接返回
                    LogUtils.getInstance().d("onFailure, but context or fragment is not active");
                    return;
                }
                if (t instanceof SocketTimeoutException || t instanceof ConnectException) {
                    // 连接异常
                    if (resultHandler.isNetDisconnected()) {
                        // 服务器连接出错(连接请求失败（超时）)
                        LogUtils.getInstance().d("onFailure, connect exception");
                        resultHandler.onFailure(new ApiException("", HttpStatusCode.CONNECT_FAIL));
                    } else {
                        // 手机网络不通
                        LogUtils.getInstance().d("onFailure, phone network exception");
                        resultHandler.onFailure(new ApiException("", HttpStatusCode.NO_NET_WORK));
                    }
                    ToastUtils.showShort(resultHandler.context, "网络连接失败，请检查您的网络连接");
                } else if (t instanceof UnknownHostException) {

//                    changeHost(url, params, dataType, resultHandler, t);
                } else {
                    // 其它异常
                    LogUtils.getInstance().d("onFailure, other exception");
                    resultHandler.onFailure(t);
                }
            }
        });
    }

    private static List<String> mAccessNetFailureUrlList = new ArrayList<>(); //访问网络失败的url集合 如果切换网络后的url在这个列表中就不用去再访问了
    private static long mDelayTime = 0;
    private static int mChangeDomainTimes = 0;


    // 处理 网络切换问题
    private static <T> void changeHost(String url, Object params, final Type dataType, final ResultHandler<T> resultHandler, Throwable t) {

        //后续将全部缓存的网络ip存入list集合
        ThreadUtils.postDelayed(new Runnable() {
            @Override
            public void run() {
                try {
                    mAccessNetFailureUrlList.add(url);
                    String OldDomain = DomainHelper.getInstance().getDomainMain();
                    String[] urlarray = url.split(OldDomain);
                    if (urlarray.length > 1) {
                        String address = urlarray[1];
                        DomainHelper.getInstance().changeDomain(url);

                        String newUrl = DomainHelper.getInstance().getDomainMain() + address;
                        if (mAccessNetFailureUrlList.contains(newUrl)) {
                            //如果切换网络后的url在这个列表中就不用去再访问了
                            resultHandler.onFailure(t);
                            return;
                        }
                        sendPostRequest(newUrl, params, dataType, resultHandler);
                        mChangeDomainTimes++;
                        if (mChangeDomainTimes == 1) {
                            mDelayTime = 0;
                        } else if (mChangeDomainTimes <= 3) {
                            mDelayTime = 1000;
                        } else if (mChangeDomainTimes <= 10) {
                            mDelayTime = 5000;
                        } else if (mChangeDomainTimes <= 20) {
                            mDelayTime = 10000;
                        } else {
                            mDelayTime = 15000;
                        }
                    } else {
                        resultHandler.onFailure(t);
                    }
                } catch (Throwable throwable) {
                    throwable.printStackTrace();
                }


            }
        }, mDelayTime);


    }

    /**
     * 网络请求结果处理类
     *
     * @param <T> 请求结果封装对象
     */
    public static abstract class ResultHandler<T> {
        Context context;
        Fragment fragment;

        public ResultHandler(Context context) {
            this.context = context;
        }

        public ResultHandler(Fragment fragment) {
            this.fragment = fragment;
        }


        /**
         * 判断网络是否未连接
         *
         * @return
         */
        public boolean isNetDisconnected() {
            return !NetworkUtils.isNetworkConnected(context);
        }

        /**
         * 请求成功时
         *
         * @param t 结果数据
         */
        public abstract void onSuccess(T t, boolean result, String msg);

        /**
         * 服务器出错
         */
        public void onServerError() {
            // 服务器处理出错
            ToastUtils.showShort(context, "服务器处理请求失败，请稍后重试");
        }

        /**
         * 请求失败时的默认处理
         * 如不需要请不调用super.onFailure(t)即可
         *
         * @param t
         */
        public void onFailure(Throwable t) {
        }

        // 检测context和fragment的生命周期
        private boolean checkLifeCycle() {
            if (this.fragment != null) {
                return LifeCycleUtils.checkFragmentLifeCycle(fragment);
            } else {
                return LifeCycleUtils.checkContextLifeCycle(context);
            }
        }
    }
}
